package com.google.code.virtualhockey.vhx.server.servlet.rest

import javax.servlet.http.{HttpServletResponse, HttpServletRequest, HttpServlet}
import com.google.code.virtualhockey.vhx.util.LangUtils
import java.util.logging.Logger
import com.google.code.virtualhockey.vhx.server.servlet.rpc.RpcCommandServiceImpl

/**
 * Basic servlet that is responsible for processing REST style commands.
 */
class RestCommandServlet extends HttpServlet {

  protected val _log = Logger.getLogger( classOf[RestCommandServlet].getName )
  
  override def doPost( req: HttpServletRequest, resp: HttpServletResponse ) { processRequest( req, resp ) }

  override def doGet( req: HttpServletRequest, resp: HttpServletResponse ) { processRequest( req, resp ) }

  /**
   * Processes all incoming requests.
   */
  protected def processRequest( rq: HttpServletRequest, rp: HttpServletResponse ) {
    rp.setContentType( "application/json" )
    val out = rp.getWriter
    val cmdrq = new RestCommandRequest( rq, rp )

    try {

    } catch {
      case t: Throwable => {
        _log.throwing( getClass.getName, "processRequest", t )
        val jsonError = createErrorResponse( cmdrq, t )
        if ( cmdrq.optJsonpCallbackError != None )
          out.write( cmdrq.optJsonpCallbackError.get + "(" + jsonError + ");" )
        //
        // as the error callback is optional for JSON-P, we try to send the error object back via the success
        // callback before resorting to pure JSON. It is up to the client to correctly interpret the received answer.
        //
        if ( cmdrq.optJsonpCallbackSuccess != None )
          out.write( cmdrq.optJsonpCallbackSuccess.get + "(" + jsonError + ");" )
        else
          out.write( jsonError );
      }
    } finally {
      out.close()
    }
  }

  protected def createErrorResponse( rq: RestCommandRequest, t: Throwable ): String = {
    var attrs: List[String] = Nil
    attrs ::= LangUtils.toJsonAttribute( "cmd", rq.optCommand.getOrElse( "None" ) )
    attrs ::= LangUtils.toJsonAttribute( "errType", t.getClass.getSimpleName )
    attrs ::= LangUtils.toJsonAttribute( "errMsg", t.getMessage )
    attrs ::= LangUtils.toJsonAttribute( "errTrace", t.getStackTraceString )

    if ( t.isInstanceOf[RestCommandException] )
      attrs ++= t.asInstanceOf[RestCommandException].getAdditionalResponseAttributes

    attrs.mkString( "{", ",\n", "}" )
  }
}
